package com.innovation.wjrpc.loader.impl;

import com.innovation.wjrpc.communication.NettyTransportClient;
import com.innovation.wjrpc.convert.ByteToJava;
import com.innovation.wjrpc.convert.JavaToByte;
import com.innovation.wjrpc.handle.NettyClientHandle;
import com.innovation.wjrpc.loader.TransportSelector;
import com.innovation.wjrpc.protocol.Peer;
import com.innovation.wjrpc.transport.TransportClient;
import com.innovation.wjrpc.util.ReflectionUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author innoyiya
 * @date 2021/9/7 19:21
 */
@Slf4j
public class RandomTransportSelector implements TransportSelector {

    private List<TransportClient> clients;

    public RandomTransportSelector() {
        clients = new ArrayList<>();
    }

    @Override
    public void init(List<Peer> peers, int count, Class<? extends TransportClient> clazz) {
        count = Math.max(count, 1);

        for (Peer peer : peers) {
            for (int i = 0; i < count; i++) {
                TransportClient client = ReflectionUtils.newInstance(clazz);
                if (client instanceof NettyTransportClient) {
                    ((NettyTransportClient) client).setHandler(new NettyClientHandle());
                    ((NettyTransportClient) client).setByteToMessageDecoder(new ByteToJava());
                    ((NettyTransportClient) client).setMessageToMessageDecoder(new JavaToByte());
                }
                client.connect(peer);
                clients.add(client);
            }
            log.info("connect server : {}", peer);
        }
    }

    @Override
    public TransportClient select() {
        int i = new Random().nextInt(clients.size());
        return clients.remove(i);
    }

    @Override
    public void release(TransportClient transportClient) {
        clients.add(transportClient);
    }

    @Override
    public void close() {
        for (TransportClient client :
                clients) {
            client.close();
        }
        clients.clear();
    }
}
